package tuplestore

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math"
	"sync"
	"time"
)

// GetByID 通过ID查询元组
func (ts *TupleStore) GetByID(id string) (*Tuple, error) {
	// 1. 通过 ID 索引查找位置
	segmentID, blockID, exists := ts.idIndex.LookupID(id)
	if !exists {
		return nil, ErrNotFound
	}

	// 2. 获取对应段和块
	ts.mu.RLock()
	segment, exists := ts.segments[segmentID]
	ts.mu.RUnlock()
	if !exists {
		return nil, fmt.Errorf("segment %s not found", segmentID)
	}

	segment.mu.RLock()
	block, exists := segment.Blocks[blockID]
	segment.mu.RUnlock()
	if !exists {
		return nil, fmt.Errorf("block %s not found in segment %s", blockID, segmentID)
	}

	// 3. 先查找增量存储
	block.mu.RLock()
	defer block.mu.RUnlock()
	if tuple := block.DeltaStore.findTuple(id); tuple != nil {
		return tuple, nil
	}

	// 4. 查找主存储
	if tuple := block.MainStore.findTuple(id); tuple != nil {
		return tuple, nil
	}

	return nil, ErrNotFound
}

// Query 条件查询元组
func (ts *TupleStore) Query(conditions []Condition) ([]*Tuple, error) {
	// 1. 分析查询条件，确定最佳索引
	index, plan := ts.selectBestIndex(conditions)

	// 2. 使用索引获取候选块
	candidateBlocks := index.findCandidateBlocks(conditions, plan)

	// 3. 并行处理候选块
	resultChan := make(chan []*Tuple, len(candidateBlocks))
	var wg sync.WaitGroup

	for _, blockRef := range candidateBlocks {
		wg.Add(1)
		go func(ref BlockRef) {
			defer wg.Done()

			ts.mu.RLock()
			segment, exists := ts.segments[ref.SegmentID]
			ts.mu.RUnlock()
			if !exists {
				return
			}

			segment.mu.RLock()
			block, exists := segment.Blocks[ref.BlockID]
			segment.mu.RUnlock()
			if !exists {
				return
			}

			// 过滤块内元组
			matches := block.queryTuples(conditions)
			resultChan <- matches
		}(blockRef)
	}

	go func() {
		wg.Wait()
		close(resultChan)
	}()

	// 4. 收集并合并结果
	allMatches := make([]*Tuple, 0)
	for matches := range resultChan {
		allMatches = append(allMatches, matches...)
	}

	return allMatches, nil
}

// selectBestIndex 选择最佳索引
func (ts *TupleStore) selectBestIndex(conditions []Condition) (*Index, *IndexPlan) {
	// TODO: 实现索引选择逻辑
	// 目前简单返回主索引
	return ts.idIndex, &IndexPlan{
		IndexType: "primary",
		Filter:    conditions,
	}
}

// findCandidateBlocks 查找候选块
func (i *Index) findCandidateBlocks(conditions []Condition, plan *IndexPlan) []BlockRef {
	i.mu.RLock()
	defer i.mu.RUnlock()

	// 如果没有条件，返回所有块
	if len(conditions) == 0 {
		blocks := make([]BlockRef, 0, len(i.items))
		for _, item := range i.items {
			blocks = append(blocks, BlockRef{
				SegmentID: item.segmentID,
				BlockID:   item.blockID,
			})
		}
		return blocks
	}

	// 使用 map 来去重
	blockMap := make(map[string]BlockRef)

	// 遍历所有索引项
	for _, item := range i.items {
		key := item.segmentID + ":" + item.blockID
		blockMap[key] = BlockRef{
			SegmentID: item.segmentID,
			BlockID:   item.blockID,
		}
	}

	// 转换为切片
	blocks := make([]BlockRef, 0, len(blockMap))
	for _, block := range blockMap {
		blocks = append(blocks, block)
	}

	return blocks
}

// findTuple 在存储中查找元组
func (ds *DeltaStore) findTuple(id string) *Tuple {
	ds.mu.RLock()
	defer ds.mu.RUnlock()
	return ds.tuples[id]
}

// findTuple 在主存储中查找元组
func (ms *MainStore) findTuple(id string) *Tuple {
	ms.mu.RLock()
	defer ms.mu.RUnlock()
	return ms.tuples[id]
}

// queryTuples 在块内查询元组
func (b *Block) queryTuples(conditions []Condition) []*Tuple {
	b.mu.RLock()
	defer b.mu.RUnlock()

	// 1. 从增量存储中查找匹配元组
	deltaMatches := make([]*Tuple, 0)
	b.DeltaStore.mu.Lock()
	for _, tuple := range b.DeltaStore.tuples {
		if matchesConditions(tuple, conditions) {
			deltaMatches = append(deltaMatches, tuple)
		}
	}
	b.DeltaStore.mu.Unlock()

	// 2. 从主存储中查找匹配元组
	mainMatches := make([]*Tuple, 0)
	b.MainStore.mu.RLock()
	for _, tuple := range b.MainStore.tuples {
		if matchesConditions(tuple, conditions) {
			mainMatches = append(mainMatches, tuple)
		}
	}
	b.MainStore.mu.RUnlock()

	// 3. 合并结果，确保不重复
	allMatches := make([]*Tuple, 0, len(deltaMatches)+len(mainMatches))
	seen := make(map[string]bool)

	// 先添加增量存储的结果
	for _, tuple := range deltaMatches {
		if !seen[tuple.ID] {
			seen[tuple.ID] = true
			allMatches = append(allMatches, tuple)
		}
	}

	// 再添加主存储的结果，跳过已存在的
	for _, tuple := range mainMatches {
		if !seen[tuple.ID] {
			seen[tuple.ID] = true
			allMatches = append(allMatches, tuple)
		}
	}

	return allMatches
}

// matchesConditions 检查元组是否满足所有条件
func matchesConditions(tuple *Tuple, conditions []Condition) bool {
	for _, cond := range conditions {
		// 从元组数据中提取对应元素，传入元组的 Schema
		element, err := extractElement(tuple.Data, cond.ElementIndex, tuple.Schema)
		if err != nil {
			return false
		}

		// 根据操作符进行条件匹配
		switch cond.Operator {
		case "=":
			if !compareEqual(element, cond.Value) {
				return false
			}
		case ">":
			if !compareGreater(element, cond.Value) {
				return false
			}
		case "<":
			if !compareLess(element, cond.Value) {
				return false
			}
		case ">=":
			if !compareGreaterEqual(element, cond.Value) {
				return false
			}
		case "<=":
			if !compareLessEqual(element, cond.Value) {
				return false
			}
		case "!=":
			if !compareNotEqual(element, cond.Value) {
				return false
			}
		default:
			return false
		}
	}
	return true
}

// extractElement 从元组数据中提取指定索引的元素
func extractElement(data []byte, index int, schema []ElementInfo) (interface{}, error) {
	if len(data) == 0 {
		return nil, fmt.Errorf("empty data")
	}

	// 使用传入的 Schema
	if index >= len(schema) {
		return nil, fmt.Errorf("invalid element index")
	}

	elementInfo := schema[index]
	offset := elementInfo.Offset

	// 检查数据长度
	if offset+elementInfo.Size > len(data) {
		return nil, fmt.Errorf("insufficient data for element at index %d", index)
	}

	// 根据元素类型提取数据
	switch elementInfo.Type {
	case TypeInt32:
		if offset+4 > len(data) {
			return nil, fmt.Errorf("insufficient data for int32")
		}
		return int32(binary.LittleEndian.Uint32(data[offset : offset+4])), nil
	case TypeInt64:
		if offset+8 > len(data) {
			return nil, fmt.Errorf("insufficient data for int64")
		}
		return int64(binary.LittleEndian.Uint64(data[offset : offset+8])), nil
	case TypeFloat32:
		if offset+4 > len(data) {
			return nil, fmt.Errorf("insufficient data for float32")
		}
		return math.Float32frombits(binary.LittleEndian.Uint32(data[offset : offset+4])), nil
	case TypeFloat64:
		if offset+8 > len(data) {
			return nil, fmt.Errorf("insufficient data for float64")
		}
		return math.Float64frombits(binary.LittleEndian.Uint64(data[offset : offset+8])), nil
	case TypeString:
		// 字符串使用固定长度
		str := string(bytes.TrimRight(data[offset:offset+elementInfo.Size], "\x00"))
		return str, nil
	case TypeBool:
		if offset >= len(data) {
			return nil, fmt.Errorf("insufficient data for bool")
		}
		return data[offset] != 0, nil
	case TypeTime:
		if offset+8 > len(data) {
			return nil, fmt.Errorf("insufficient data for time")
		}
		return time.Unix(0, int64(binary.LittleEndian.Uint64(data[offset:offset+8]))), nil
	default:
		return nil, fmt.Errorf("unknown element type: %d", elementInfo.Type)
	}
}

// 比较函数
func compareEqual(a, b interface{}) bool {
	// 尝试将两个值转换为相同的类型
	aVal, bVal, err := convertToSameType(a, b)
	if err != nil {
		return false
	}

	switch v1 := aVal.(type) {
	case int32:
		if v2, ok := bVal.(int32); ok {
			return v1 == v2
		}
	case int64:
		if v2, ok := bVal.(int64); ok {
			return v1 == v2
		}
	case float32:
		if v2, ok := bVal.(float32); ok {
			return v1 == v2
		}
	case float64:
		if v2, ok := bVal.(float64); ok {
			return v1 == v2
		}
	case string:
		if v2, ok := bVal.(string); ok {
			return v1 == v2
		}
	case bool:
		if v2, ok := bVal.(bool); ok {
			return v1 == v2
		}
	case time.Time:
		if v2, ok := bVal.(time.Time); ok {
			return v1.Equal(v2)
		}
	}
	return false
}

// convertToSameType 将两个值转换为相同的类型
func convertToSameType(a, b interface{}) (interface{}, interface{}, error) {
	switch v1 := a.(type) {
	case int32:
		switch v2 := b.(type) {
		case int32:
			return v1, v2, nil
		case int64:
			return int64(v1), v2, nil
		case float32:
			return float32(v1), v2, nil
		case float64:
			return float64(v1), v2, nil
		}
	case int64:
		switch v2 := b.(type) {
		case int32:
			return v1, int64(v2), nil
		case int64:
			return v1, v2, nil
		case float32:
			return float32(v1), v2, nil
		case float64:
			return float64(v1), v2, nil
		}
	case float32:
		switch v2 := b.(type) {
		case int32:
			return v1, float32(v2), nil
		case int64:
			return v1, float32(v2), nil
		case float32:
			return v1, v2, nil
		case float64:
			return float64(v1), v2, nil
		}
	case float64:
		switch v2 := b.(type) {
		case int32:
			return v1, float64(v2), nil
		case int64:
			return v1, float64(v2), nil
		case float32:
			return v1, float64(v2), nil
		case float64:
			return v1, v2, nil
		}
	case string:
		if v2, ok := b.(string); ok {
			return v1, v2, nil
		}
	case bool:
		if v2, ok := b.(bool); ok {
			return v1, v2, nil
		}
	case time.Time:
		if v2, ok := b.(time.Time); ok {
			return v1, v2, nil
		}
	}
	return nil, nil, fmt.Errorf("cannot convert types: %T and %T", a, b)
}

func compareGreater(a, b interface{}) bool {
	switch v1 := a.(type) {
	case int32:
		if v2, ok := b.(int32); ok {
			return v1 > v2
		}
	case int64:
		if v2, ok := b.(int64); ok {
			return v1 > v2
		}
	case float32:
		if v2, ok := b.(float32); ok {
			return v1 > v2
		}
	case float64:
		if v2, ok := b.(float64); ok {
			return v1 > v2
		}
	case string:
		if v2, ok := b.(string); ok {
			return v1 > v2
		}
	case time.Time:
		if v2, ok := b.(time.Time); ok {
			return v1.After(v2)
		}
	}
	return false
}

func compareLess(a, b interface{}) bool {
	switch v1 := a.(type) {
	case int32:
		if v2, ok := b.(int32); ok {
			return v1 < v2
		}
	case int64:
		if v2, ok := b.(int64); ok {
			return v1 < v2
		}
	case float32:
		if v2, ok := b.(float32); ok {
			return v1 < v2
		}
	case float64:
		if v2, ok := b.(float64); ok {
			return v1 < v2
		}
	case string:
		if v2, ok := b.(string); ok {
			return v1 < v2
		}
	case time.Time:
		if v2, ok := b.(time.Time); ok {
			return v1.Before(v2)
		}
	}
	return false
}

func compareGreaterEqual(a, b interface{}) bool {
	return compareGreater(a, b) || compareEqual(a, b)
}

func compareLessEqual(a, b interface{}) bool {
	return compareLess(a, b) || compareEqual(a, b)
}

func compareNotEqual(a, b interface{}) bool {
	return !compareEqual(a, b)
}
